package components
{
	import flash.display.Shape;
	import flash.events.NetStatusEvent;
	import flash.events.SecurityErrorEvent;
	import flash.events.SyncEvent;
	import flash.net.NetConnection;
	import flash.net.SharedObject;
	import flash.utils.ByteArray;
	
	import mx.containers.Canvas;
	import mx.controls.Image;
	import mx.controls.Text;
	import mx.core.FlexGlobals;
	import mx.core.UIComponent;
	
	import objecthandles.ObjectHandles;

	public class SharedDashboardManager
	{
		static private var instance : SharedDashboardManager;
		
		private var model: Model = Model.getInstance();
		
		private var _nc:NetConnection;
		public var users_so:SharedObject;
		public var dashboard_so:SharedObject;
		public var bckgndColor_so:SharedObject;
		
		private var oh:ObjectHandles;
		private var dashboard: Canvas;
		private var UIRef: UIComponent;
		
		[Bindable]
		[Embed(source="assets/resizeicons/resize_handle.png")]
		private static var resize_handle:Class;
		
		[Bindable]
		[Embed(source="assets/resizeicons/rotate_handle.png")]
		private static var rotate_handle:Class;
		
		static public function getInstance() : SharedDashboardManager 
		{
			if ( instance == null ) 
			{
				instance = new SharedDashboardManager( new Lock() );
			}
			
			return instance;
		}
		
		public function SharedDashboardManager( lock : Lock ) : void 
		{
			if ( lock == null ) 
			{
				throw new Error( "Use getInstance() method instead" );
			}
		}
		
		public function set nc(nc:NetConnection):void 
		{
			_nc = nc;
			dashboard_so = SharedObject.getRemote("Dashboard", _nc.uri);
			bckgndColor_so = SharedObject.getRemote("BckgndColor", _nc.uri);
		}
		
		public function get nc():NetConnection 
		{
			return _nc;
		}
		
		
		public function netSecurityError(event:SecurityErrorEvent):void {
			trace("netSecurityError: " + event);
		}
		
		/** 
		 * it is passed an event that contains the information object.
		 */
		public function onNetStatusChange(event:NetStatusEvent):void 
		{
			var info:Object = event.info;
			
			switch (info.code) 
			{
				case "NetConnection.Connect.Success" :
					users_so = SharedObject.getRemote("ChatUsers", nc.uri);
					if(users_so){
						users_so.addEventListener(SyncEvent.SYNC, UsersOnSync);
						users_so.connect(nc);
						users_so.client = this; // refers to the scope of application and public funtions
					}
					
					dashboard_so = SharedObject.getRemote("Dashboard", nc.uri);
					if(dashboard_so){
						dashboard_so.addEventListener(SyncEvent.SYNC, DashboardOnSync);
						dashboard_so.connect(nc);
						dashboard_so.client = this; // refers to the scope of application and public funtions
					}
					
					bckgndColor_so = SharedObject.getRemote("BckgndColor", nc.uri);
					if(bckgndColor_so){
						bckgndColor_so.addEventListener(SyncEvent.SYNC, BckgndColorOnSync);
						bckgndColor_so.connect(nc);
						bckgndColor_so.client = this; // refers to the scope of application and public funtions
					}
					
					break;
				case "NetConnection.Connect.Closed" :
					break;
				case "NetConnection.Connect.Failed" :
					break;
				case "NetConnection.Connect.Rejected" :
					break;
				default :
					//statements
					break;
			}
		}
		
		private function UsersOnSync(event:SyncEvent):void 
		{
			var temp:Array = new Array();
			for(var p:String in users_so.data){ 
				temp.push(users_so.data[p]);
			}
			
			//update list of users
			FlexGlobals.topLevelApplication.dashboardCpnt.chat.connUsersArr = temp;
		}
		
		private function BckgndColorOnSync(event:SyncEvent):void 
		{							
			FlexGlobals.topLevelApplication.dashboardCpnt.sidebar.bckgndColor.selectedColor = bckgndColor_so.data["color"];
		}
		
		private function DashboardOnSync(event:SyncEvent):void 
		{
			var changeList:Array = event.changeList;
			
			for(var i:String in changeList)
			{				
				if((changeList[i].code == "success" || changeList[i].code == "change") && changeList[i].name.substring(0,3) == "txt")
				{
					var text:Text = new Text();
					text.htmlText = dashboard_so.data[ changeList[i].name ];
					
					oh = new ObjectHandles();
					oh.id = changeList[i].name;
					oh.height = 100;
					oh.width = 200;
					oh.resizeHandleImage = resize_handle;
					oh.allowRotate = false;
					oh.x = 10; oh.y = 10;
					oh.minHeight = 40; oh.minWidth = 80;
					text.percentWidth = 100;
					text.percentHeight = 100;
					oh.addChild(text);
					FlexGlobals.topLevelApplication.dashboardCpnt.dashboard.addChild( oh );
					model.saveText(text.htmlText);
				} 
				else if((changeList[i].code == "success" || changeList[i].code == "change") && changeList[i].name.substring(0,3) == "img")
				{
					var imgData:Array = dashboard_so.data[ changeList[i].name ];
					
					oh = new ObjectHandles();
					oh.id = changeList[i].name;
					oh.x = imgData[1];
					oh.y = imgData[2];
					oh.width = imgData[3];	
					oh.height = imgData[4];
					oh.allowRotate = true;
					oh.resizeHandleImage = resize_handle;
					oh.rotateHandleImage = rotate_handle;
					
					var img:Image = new Image();
					img.source = imgData[0];					
					img.percentWidth = 100;
					img.percentHeight = 100;
					img.maintainAspectRatio = false;
					
					oh.addChild(img);
					FlexGlobals.topLevelApplication.dashboardCpnt.dashboard.addChild( oh );
					model.saveImage(imgData);
				} 
				else if((changeList[i].code == "success" || changeList[i].code == "change") && changeList[i].name.substring(0,3) == "shp")
				{
					var shape:Shape = dashboard_so.data[ changeList[i].name ] as Shape;
					FlexGlobals.topLevelApplication.dashboardCpnt.UIRef.addChild(shape);
					model.saveShape(shape);
				} 
				else if( changeList[i].code == "delete" )
				{
					if(model.data.length > 0)
					{
						var lastAddedObject: Object = model.data.getItemAt(model.data.length - 1);
						if ( lastAddedObject.id.substring(0,3) == "img" || lastAddedObject.id.substring(0,3) == "txt" )
						{
							dashboard = FlexGlobals.topLevelApplication.dashboardCpnt.dashboard;
							if(dashboard.numChildren > 1)
								dashboard.removeChild(dashboard.getChildAt(dashboard.numChildren -1));
						}
						else if (lastAddedObject.id.substring(0,3) == "shp")
						{
							UIRef = FlexGlobals.topLevelApplication.dashboardCpnt.UIRef;
							if(UIRef.numChildren > 0)
								UIRef.removeChild(UIRef.getChildAt(UIRef.numChildren -1));
						}
					}
					model.removeLastItem();
				}
			}
		}
		
	
		public function addImage(imgData: Array):void
		{
			dashboard_so.setProperty("img" + model.itemId, imgData);
		}
		
		public function addShape(shape: Shape):void
		{
			dashboard_so.setProperty("shp" + model.itemId, shape);
		}
		
		public function addText(text: String):void
		{
			dashboard_so.setProperty("txt" + model.itemId, text);
		}
		
		public function removeLastItem():void
		{
			if(model.data.length > 0)
			{
				var itemId: String = model.data.getItemAt( model.data.length -1 ).id;
				dashboard_so.setProperty(itemId, null);
			}
		}
		
		public function removeItemById(itemId: String):void
		{
			dashboard_so.setProperty(itemId, null);
		}
		
		public function removeAllItems():void
		{
			for(var p:String in dashboard_so.data){ 
				dashboard_so.setProperty(p, null);
			}
		}
		
		public function changeBckgndColor(color: Number):void
		{
			bckgndColor_so.setProperty("color", color);
		}
		
		public function msgFromSrvr(msg:String):void{
			FlexGlobals.topLevelApplication.dashboardCpnt.chat.writeMessage(msg);
		}	
	}
}

internal class Lock{}
